package controllers

import java.util.Date

import DB._
import common.Tool._
import common._
import io.swagger.annotations._
import play.api.Logger
import play.api.mvc.{Request, AnyContent}

import scala.util.Random
import scala.util.parsing.json.{JSON => SJSON}
import common.JedisCacheKeys._


/**
  * Created by 林 on 2015-10-9.
  */
@Api(value = "/admin", description = "管理员相关接口")
object AdminController extends BaseController {

  /**
    * 通用查询方法
    *
    * @param table    需要查询的表实例
    * @param keywords 需要搜索的关键字
    * @param fun      数据转换函数
    * @param orderBy  排序
    * @param request  请求数据
    * @return 开箱可用的结果
    */
  def adminListMethod(table: DBEntity, keywords: List[String], fun: DBEntity => AnyRef = BaseDBEntity.toHashMap, orderBy: String = "id desc")(implicit request: Request[AnyContent]) = {
    val List(name) = getQuery("name")
    val gp = getPage
    val where = if (isEmpty(name)) "" else keywords.map(v => s"${v} like '%${name}%'").mkString(" or ")
    val (count, roles) = table.queryPage(where, gp._1, gp._2, orderBy)
    jsonListRequest(roles.map(fun), gp._1, count, gp._2)
  }

  /**
    * 通用删除方法
    *
    * @param ids   id列表
    * @param table 表
    * @param field 字段
    * @return 开箱可用的结果
    */
  def adminDeleteMethod(ids: String, table: DBEntity, field: String = "id") = {
    ids.toIntList("_").map(v => DBEntity.sql(s"delete from ${table.tableName} where $field = ?", v))
    Ok(ajaxOk)
  }

  /**
    * 通用增加方法
    *
    * @param fields  需要添加的字段
    * @param table   表
    * @param fun     请求处理函数
    * @param withId  是否插入id
    * @param request 请求
    * @tparam T 类型
    * @return 开箱可用的结果
    */
  def adminAddMethod[T <: BaseDBEntity[T]](fields: List[String], table: T, fun: Map[String, String] => Map[String, Any] = v => v, withId: Boolean = false)(implicit request: Request[AnyContent]) = {
    val data = fun(fields.map(v => v -> getBody(v).head).toMap)
    val orgMap = table.toHashMap
    data.foreach { kv =>
      orgMap.put(kv._1, kv._2)
    }
    val ent = table.fromJson(orgMap.toJson)
    if (!withId) {
      ent.insert()
    } else {
      ent.insertWithId()
    }
    Ok(ajaxOk)
  }

  /**
    * 通用修改方法
    *
    * @param fields  需要添加的字段
    * @param table   表
    * @param idName  跟新依赖字段
    * @param fun     请求处理函数
    * @param request 请求
    * @tparam T 类型
    * @return 开箱可用的结果
    */
  def adminUpdateMethod[T <: BaseDBEntity[T]](fields: List[String], table: T, idName: String = "id", fun: Map[String, String] => Map[String, Any] = v => v)(implicit request: Request[AnyContent]) = {
    val data = fun(fields.map(v => v -> getBody(v).head).toMap)
    val orgMap = table.toHashMap
    data.foreach { kv =>
      orgMap.put(kv._1, kv._2)
    }
    table.fromJson(orgMap.toJson).update(idName, fields: _*)
    Ok(ajaxOk)
  }


  def toLogin = Action.async { implicit request =>
    Assets.at("/public", "index.html").apply(request)
  }

  @ApiOperation(nickname = "login", value = "管理员登陆", notes = "管理员登陆", response = classOf[User], httpMethod = "GET")
  @ApiImplicitParams(Array(
    new ApiImplicitParam(name = "name", value = "管理员账号", required = true, dataType = "string", paramType = "body"),
    new ApiImplicitParam(name = "pwd", value = "管理员密码", required = true, dataType = "string", paramType = "body")))
  def login = JsAction {
    implicit request =>
      val List(adminName, adminPassword) = getBody("name", "pwd")
      keyLimit(ip, 5, 60)
      keyLimit(adminName, 6, 60)
      val admin = new Admin().queryOne("adminName=?", adminName)
      if (admin.isEmpty) throw new NoUserExcepiton
      val a = admin.get
      if (adminPassword.encrypt() != a.adminPassword) {
        throw new LoginFailException
      }
      val role = new RoleGroup().queryById(a.roleId).orNull
      if (role == null) throw new AdminNoInitExcepiton
      val roles = if (role.roles != "*") new Role().queryByIds(role.roles.split(",").toList) else new Role().queryAll
      val names = roles map (_.partten) filter (_ != null) distinct
      val list = names map (n => Map("name" -> n, "sub" -> (roles filter (_.partten == n) map (r => Map("name" -> r.name, "url" -> r.path)))))
      val rules = roles.map(r => (r.name + "," + r.method + ":" + r.path).toLowerCase()).toJson
      JedisTool.useJedis(_.hset("admin_roles", a.id, rules))
      keyUnlimit(ip)
      keyUnlimit(adminName)
      Ok(Map("code" -> 200, "msg" -> "成功", "bean" -> Map("user" -> Map("id" -> a.id.toString, "name" -> a.adminName, "role" -> role.name), "authlist" -> list)).toJson)
        .withSession(request.session +("admin", a.toJson.encrypt) +("adminName", a.adminName) +("adminid", a.id.toString))
  }

  def loginCheck = JsAction { implicit request =>
    Ok(request.session.get("adminid").isDefined + "")
  }

  /**
    * 退出登录
    *
    * @return
    */
  def logout = JsAction {
    Ok(ajaxOk).withNewSession
  }

  /**
    * 系统设置
    */
  def getSystemSetting = AdminAction { implicit request =>
    adminListMethod(new Setting(), "name" :: Nil)
  }

  def updateSystemSetting(id: Int) = AdminAction { implicit request =>
    val v = adminUpdateMethod(List("name", "value", "remark"), new Setting(id))
    cacheServer ! SETTING_MESSAGE_KEY
    v
  }

  def addSystemSetting = AdminAction { implicit request =>
    val v = adminAddMethod(List("name", "value", "remark"), new Setting())
    cacheServer ! SETTING_MESSAGE_KEY
    v
  }

  def deleteSystemSetting(id: String) = AdminAction {
    adminDeleteMethod(id, new Setting())
  }

  /**
    * 管理员
    */
  def getAdminUsers = AdminAction { implicit request =>
    val names = cacheMethod("admin_group_name_cache", 10) {
      new RoleGroup().queryAll()
    }.map(g => g.id -> g.name).toMap
    adminListMethod(new Admin(), "adminName" :: Nil, { data =>
      val om = data.asInstanceOf[Admin].toHashMap
      om("roleName") = names(data.asInstanceOf[Admin].roleId)
      om
    })
  }

  def addAdmin = AdminAction { implicit request =>
    adminAddMethod(List("adminName", "adminPassword", "roleId", "isEffect"), new Admin(), { m =>
      m.map { kv =>
        kv._1 match {
          case "adminPassword" => kv._1 -> kv._2.encrypt()
          case "isEffect" => kv._1 -> kv._2.toInt
          case "roleId" => kv._1 -> kv._2.toInt
          case _ => kv._1 -> kv._2
        }
      }
    })
  }

  def Admin(id: Int) = AdminAction { implicit request =>
    adminUpdateMethod(List("adminName", "adminPassword", "roleId", "isEffect"), new Admin(id), fun = { m =>
      m.map { kv =>
        kv._1 match {
          case "adminPassword" => kv._1 -> kv._2.encrypt()
          case "isEffect" => kv._1 -> kv._2.toInt
          case "roleId" => kv._1 -> kv._2.toInt
          case _ => kv._1 -> kv._2
        }
      }
    })
  }

  def delAdmin(id: String) = AdminAction {
    adminDeleteMethod(id, new Admin())
  }

  /**
    * 部门
    */

  def getAdminGroups = AdminAction { implicit request =>
    adminListMethod(new RoleGroup(), "name" :: Nil)
  }

  def adminGroups = AdminAction {
    implicit request =>
      val rolegroups = new RoleGroup().queryAll()
      Ok(rolegroups.toJson).withHeaders("Cache-Control" -> "no-cache", "Content-Type" -> "application/json; charset=utf-8")
  }

  def AdminGroup(id: Int) = AdminAction { implicit request =>
    adminUpdateMethod(List("name", "roles"), new RoleGroup(id))
  }

  def delAdminGroup(id: String) = AdminAction {
    adminDeleteMethod(id, new RoleGroup())
  }

  def addAdminGroup = AdminAction { implicit request =>
    adminAddMethod(List("name", "roles"), new RoleGroup())
  }

  /**
    * 权限
    */
  def roles = AdminAction {
    implicit request =>
      val rolegroups = new Role().queryAll()
      Ok(rolegroups.toJson).withHeaders("Cache-Control" -> "no-cache", "Content-Type" -> "application/json; charset=utf-8")
  }

  def getAuthoritys = AdminAction { implicit request =>
    adminListMethod(new Role(), "name" :: Nil)
  }

  def updateAuthority(id: Int) = AdminAction { implicit request =>
    adminUpdateMethod(List("path", "method", "name", "partten"), new Role(id))
  }

  def delAuthority(id: String) = AdminAction {
    adminDeleteMethod(id, new Role())
  }

  def addAuthority = AdminAction { implicit request =>
    adminAddMethod(List("path", "method", "name", "partten"), new Role())
  }

  /**
    * 管理日志
    */
  def getAdminLog = AdminAction { implicit request =>
    adminListMethod(new AdminModifyLog(), "adminName" :: "name" :: Nil)
  }




  /**
    * 微信号
    */
  def apps = AdminAction {
    implicit request =>
      val rolegroups = new App().queryAll()
      Ok(rolegroups.toJson).withHeaders("Cache-Control" -> "no-cache", "Content-Type" -> "application/json; charset=utf-8")
  }
  def getApps = AdminAction {implicit request =>
    adminListMethod(new App(),"name"::Nil,{ data =>
      val om = data.asInstanceOf[App].toHashMap
      om("allMoney") =  data.asInstanceOf[App].allMoney.toDouble/100
      om("dayMoney") =JedisTool.useJedis(_.get(APP_DAY_MONEY_KEY+new Date().sdate+"_"+data.asInstanceOf[App].id).map(_.toInt.toDouble/100).getOrElse(0d))
      om
    })
  }
  def updateApp(id: Int) = AdminAction {implicit request =>
    adminUpdateMethod(List("name","appid","appsecr","dayLimit","allLimit","rule"),new App(id))
  }
  def delApp(id: String) = AdminAction {adminDeleteMethod(id,new App())}
  def addApp = AdminAction {implicit request =>
    adminAddMethod(List("name","appid","appsecr","dayLimit","allLimit","rule"),new App())
  }



  /**
    * 用户
    */
  def getUsers = AdminAction {implicit request =>
    adminListMethod(new User(),"name"::Nil)
  }
  def updateUser(id: Int) = AdminAction {implicit request =>
    adminUpdateMethod(List("name"),new User(id))
  }
  def delUser(id: String) = AdminAction {adminDeleteMethod(id,new User())}
  def addUser = AdminAction {implicit request =>
    adminAddMethod(List("name"),new User())
  }



  /**
    * 订单
    */
  def getOrders = AdminAction {implicit request =>
    val names = cacheMethod("admin_app_name_cache", 10) {
      new App().queryAll()
    }.map(g => g.id -> g.name).toMap
    val users = cacheMethod("admin_user_name_cache", 10) {
      new User().queryAll()
    }.map(g => g.id -> g).toMap
    adminListMethod(new Order(),"remark"::Nil,{ data =>
      val om = data.asInstanceOf[Order].toHashMap
      om("appName") = names.getOrElse(data.asInstanceOf[Order].appid,"已删除公众号")
      om("userName") = users.get(data.asInstanceOf[Order].uid).map(_.name).getOrElse("已删除用户(神秘用户)")
      om("icon") = users(data.asInstanceOf[Order].uid).icon
      om("amount") =  data.asInstanceOf[Order].amount.toDouble/100
      om("status") = if(data.asInstanceOf[Order].status==1) "成功" else if(data.asInstanceOf[Order].status==2) "失败" else "处理中"
      om
    },"createDate desc")
  }
  def updateOrder(id: Int) = AdminAction {implicit request =>
    adminUpdateMethod(List("remark"),new Order(id))
  }
  def delOrder(id: String) = AdminAction {adminDeleteMethod(id,new Order())}
  def addOrder = AdminAction {implicit request =>
    //TODO 需要给用户发一个红包
    adminAddMethod(List("uid","appid","remark","amount"),new Order())
  }

  //数据导出
  def exprot = AdminAction {
    implicit request =>
      val names = cacheMethod("admin_app_name_cache", 10) {
        new App().queryAll()
      }.map(g => g.id -> g.name).toMap
      val users = cacheMethod("admin_user_name_cache", 10) {
        new User().queryAll()
      }.map(g => g.id -> g).toMap
      val (count, orders) = new Order().queryPage("", 1, Int.MaxValue, "createDate desc")
      val head = List("id" -> "编号", "uid" -> "用户编号", "userName" -> "用户名", "amount" -> "金额",
        "wxid" -> "微信编号","wxname" -> "微信号", "createDate" -> "创建时间",
        "status" -> "状态", "remark" -> "系统备注")
      val statusStrList = List("已提交", "成功", "失败")
      val fileContent = head.map(_._2).mkString(",") + "\r\n" +
        orders.map(o => List(o.id, o.uid, users.get(o.uid).map(_.name).getOrElse("已删除用户(神秘用户)"), o.amount,o.appid,names.getOrElse(o.appid,"已删除公众号"),
          o.createDate.sdatetime, statusStrList(o.status), o.remark).mkString(",")).mkString("\r\n")
      Ok(fileContent.getBytes("gbk")).withHeaders(("Content-Type" -> "application/x-excel;charset=gbk"), ("Content-Disposition" -> "attachment; filename=data.csv"))
  }

}
      